#include "stdafx.h"
#include <Strsafe.h>
#include "PebDev.h"

#define	EXP(x)	((x&0x200)?x|0xfc00:x)

HPEN	PebDev::penR,PebDev::penG,PebDev::penB,PebDev::penW;

PebDev::PebDev(HDEVINFO devInfo,SP_DEVICE_INTERFACE_DATA *devData):
	UsbHid(devInfo,devData){
	accidx=0;
	imgIdx=0;
	imgMax=0;
	imgMin=0xffff;
	imgPtr=0;
	voltS=0;
	voltC=0;
	memset(accx,0,sizeof(accx));
	memset(accy,0,sizeof(accy));
	memset(accz,0,sizeof(accz));
	if(!penR){
		penR=CreatePen(PS_SOLID,0,RGB(255,0,0));
		penG=CreatePen(PS_SOLID,0,RGB(0,255,0));
		penB=CreatePen(PS_SOLID,0,RGB(0,0,255));
		penW=CreatePen(PS_SOLID,4,RGB(255,255,255));
	}
}

void PebDev::cleanup(void){
	DeleteObject(penW);
	DeleteObject(penB);
	DeleteObject(penG);
	DeleteObject(penR);
}
UsbHid* PebDev::create(HDEVINFO devInfo,SP_DEVICE_INTERFACE_DATA *devData){
	return new PebDev(devInfo,devData);
}
void PebDev::drawAcc(void){
	uint *e,*p,v;
	short k,x,y,z;
	HDC	hdc=GetDC(window);
	HGDIOBJ old=SelectObject(hdc,penW);
	k=accidx-1;
	if(k<0)
		k=MAX_ACC-1;
	x=accx[k];
	y=accy[k];
	z=accz[k];
	for(p=(uint*)(report.data),e=(uint*)(report.data+15);p<e;){
		SelectObject(hdc,penW);
		MoveToEx(hdc,accidx+2,0,NULL);
		LineTo(hdc,accidx+2,1000);
		v=*p++;
		k=v&0x3ff;
		k=EXP(k);
		SelectObject(hdc,penR);
		MoveToEx(hdc,accidx-1,x+500,NULL);
		LineTo(hdc,accidx,k+500);
		accx[accidx]=x=k;
		k=(v>>11)&0x3ff;
		k=EXP(k);
		SelectObject(hdc,penG);
		MoveToEx(hdc,accidx-1,y+500,NULL);
		LineTo(hdc,accidx,k+500);
		accy[accidx]=y=k;
		k=(v>>22)&0x3ff;
		k=EXP(k);
		SelectObject(hdc,penB);
		MoveToEx(hdc,accidx-1,z+500,NULL);
		LineTo(hdc,accidx,k+500);
		accz[accidx]=z=k;
		SetPixel(hdc,accidx,500,RGB(127,127,127));
		accidx++;
		if(accidx>=MAX_ACC)
			accidx=0;
	}
	SelectObject(hdc,old);
	ReleaseDC(window,hdc);
}
void PebDev::openAll(void){
	UsbHid::openAll(create);
}
void PebDev::sendReport(Report* buffer){
	if(buffer){
		UsbHid::sendReport(&buffer->report[3],sizeof(Report)-3);
		if(buffer->cmd==RPT_FIRMWARE)
			upgord=buffer->ord;
	}
}
void PebDev::single(ushort key,ushort val){
	switch(key){
	case RPT_STEPSLO:
		curSteps=(curSteps&0xffff0000)|val;
		break;
	case RPT_STEPSHI:
		curSteps=(curSteps&0xffff)|((uint)val<<16);
		break;
	case RPT_OFFSETLO:
		offset=(offset&0xffff0000)|val;
		break;
	case RPT_OFFSETHI:
		offset=(offset&0xffff)|((uint)val<<16);
		break;
	case RPT_TICKLO:
		tick=(tick&0xffff0000)|val;
		break;
	case RPT_TICKHI:
		tick=(tick&0xffff)|((uint)val<<16);
		break;
	case RPT_VERSION:
		version=val;
		upgrade.loadBin(serialNum,val);
		break;
	case RPT_VOLTS:
		voltS=val;
		break;
	case RPT_VOLTC:
		voltC=val;
	}
}
void PebDev::multiple(void){
	ushort o;
	switch(report.cmd){
	case RPT_ACCREC:
		drawAcc();
		break;
	case RPT_DATAIMG:
		o=report.ord;
		if(o==imgPtr){
			imgIdx=o;
			if(imgMax<imgIdx)
				imgMax=imgIdx;
			if(imgMin>imgIdx)
				imgMin=imgIdx;
			imgPtr=o+60;
		}
		break;
	case RPT_FIRMWARE:
		sendReport(upgrade.upgrade(&report));
		break;
	}
}
uint PebDev::threadEntry(void){
	while(1){
		if(getReport(&report.report[3],sizeof(report)-3)){
			HDC	hdc=GetDC(window);
			wchar_t x[1024];
			if(report.cmd&0x8000){
				multiple();
				StringCbPrintf(x,sizeof(x),_T("image: %d, %d, %d ----"),imgIdx,imgMin,imgMax);
				TextOut(hdc,0,80,x,lstrlen(x));
				StringCbPrintf(x,sizeof(x),_T("%x ----"),upgord);
				TextOut(hdc,0,100,x,lstrlen(x));
			}else{
				ushort *e,*p=(ushort*)&report.cmd,i,v;
				for(e=p+32;p<e;){
					i=*p++;
					v=*p++;
					single(i,v);
				}
				uint t=localTick();
				StringCbPrintf(x,sizeof(x),_T("steps: %u, %u ----"),
					curSteps,ystSteps);
				TextOut(hdc,0,0,x,lstrlen(x));
				StringCbPrintf(x,sizeof(x),_T("ticks: %u, %u, %u ----"),
					tick+offset,t,offset);
				TextOut(hdc,0,20,x,lstrlen(x));
				StringCbPrintf(x,sizeof(x),_T("volt: %u, %u ----"),voltC,voltS);
				TextOut(hdc,0,40,x,lstrlen(x));
				StringCbPrintf(x,sizeof(x),_T("version: %04x ----"),version);
				TextOut(hdc,0,60,x,lstrlen(x));
				int a=tick+offset-t;
				if(a<0)
					a=-a;
				if(a>5){
					memset(&report,0,sizeof(report));
					report.cmd=RPT_TICKLO;
					report.ord=LOWORD(t);
					report.data[0]=RPT_TICKHI;
					report.data[1]=HIWORD(t);
					sendReport(&report);
				}else sendReport(upgrade.upgrade(0));
			}
			ReleaseDC(window,hdc);
		}
		else break;
	}
	return 0;
}